package com.wantong.jianpu.net;


import com.trello.rxlifecycle2.LifecycleProvider;
import com.wantong.jianpu.app.XApp;
import com.wantong.jianpu.utils.ConfigUtils;
import com.wantong.jianpu.utils.Constants;

import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.Observer;
import io.reactivex.functions.Function;
import me.goldze.mvvmhabit.utils.KLog;
import me.goldze.mvvmhabit.utils.RxUtils;
import me.goldze.mvvmhabit.utils.SPUtils;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * @author PACY
 * 创建时间 19/1/9 14:36.
 * 邮箱 pengwwe457621023@qq.com
 * 类描述 RetrofitUtil
 */
public class RetrofitUtil {
    private static final int TIME_OUT = 120;//超时时间
    private static ApiService mApiService;

    public static ApiService getApiService() {
        if (mApiService == null) {


            Interceptor interceptor = chain -> {
                Request original = chain.request();
                Request request;
                //如果token不为空则添加token到参数列表
                request = original.newBuilder()
                        .addHeader("Content-Type", "application/json")
                        .addHeader("Authorization", "Bearer " + SPUtils.getInstance(Constants.LOGIN_SP_TAG).getString(Constants.TOKEN))
                        .method(original.method(), original.body())
                        .build();
                return chain.proceed(request);
            };
            //缓存拦截器
            //缓存时间
            int CACHE_TIMEOUT = 10 * 1024 * 1024;
//            //缓存存放的文件
//            File httpCacheDirectory = new File(mContext.getCacheDir(), "goldze_cache");
//            //缓存对象
//            Cache cache = new Cache(httpCacheDirectory, CACHE_TIMEOUT);
//            okHttpClientBuilder.cache(cache).addInterceptor(new CacheInterceptor(mContext));

            OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
            //设置请求超时时长
            okHttpClientBuilder
                    .addInterceptor(interceptor)
                    .addInterceptor(getHttpLoggingInterceptor())
                    .addNetworkInterceptor(new TokenInterceptor())
                    .connectTimeout(TIME_OUT, TimeUnit.SECONDS);

            Retrofit retrofit = new Retrofit.Builder()
                    //服务器地址
                    .baseUrl(ConfigUtils.BASE_URL)
                    //配置转化库，采用Gson
                    .addConverterFactory(GsonConverterFactory.create())
                    //配置回调库，采用RxJava
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    //设置OKHttpClient为网络客户端
                    .client(okHttpClientBuilder.build()).build();

            mApiService = retrofit.create(ApiService.class);
        }
        return mApiService;
    }

    //提供Log日志插值器
    public static HttpLoggingInterceptor getHttpLoggingInterceptor() {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(message -> {
            if(XApp.isDebug){
                KLog.i(message);
            }
        });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return loggingInterceptor;
    }

    /**
     * 对observable进行统一转换（用于非文件下载请求）
     *
     * @param observable 被订阅者
     * @param observer   订阅者
     */
    public static void composeToSubscribe(Observable observable, Observer observer, LifecycleProvider lifecycle) {
        observable.compose(getTransformer(lifecycle)).subscribe(observer);
    }

    /**
     * 获取统一转换用的Transformer（用于非文件下载请求）
     */
    public static <T> ObservableTransformer getTransformer(LifecycleProvider lifecycle) {
        return upstream -> {

            //当lifecycleObservable发射事件时，终止操作。
            //统一在请求时切入io线程，回调后进入ui线程
            //加入失败重试机制（延迟3秒开始重试，重试3次）
            return upstream
//                    .retryWhen(new RetryFunction(3, 3))
                    .compose(RxUtils.bindToLifecycle(lifecycle))
                    .compose(RxUtils.schedulersTransformer())
                    .compose(RxUtils.exceptionTransformer());
        };
    }

    //请求失败重试机制
    public static class RetryFunction implements Function<Observable<Throwable>, ObservableSource<?>> {

        private int retryDelaySeconds;//延迟重试的时间
        private int retryCount;//记录当前重试次数
        private int retryCountMax;//最大重试次数

        public RetryFunction(int retryDelaySeconds, int retryCountMax) {
            this.retryDelaySeconds = retryDelaySeconds;
            this.retryCountMax = retryCountMax;
        }

        @Override
        public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {

            //方案二：使用全局变量来控制重试次数，重试3次后不再重试，通过代码显式回调onError结束请求
            return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                @Override
                public ObservableSource<?> apply(Throwable throwable) throws Exception {
                    //如果失败的原因是UnknownHostException（DNS解析失败，当前无网络），则没必要重试，直接回调error结束请求即可
                    if (throwable instanceof UnknownHostException) {
                        return Observable.error(throwable);
                    }

                    //没超过最大重试次数的话则进行重试
                    if (++retryCount <= retryCountMax) {
                        //延迟retryDelaySeconds后开始重试
                        return Observable.timer(retryDelaySeconds, TimeUnit.SECONDS);
                    }

                    return Observable.error(throwable);
                }
            });
        }
    }

}
